package com.zbo.servlet;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zbo.pojo.Sc;
import com.zbo.service.ScService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

@WebServlet("/course")
public class CourseManageServlet extends HttpServlet {

    private final ScService scService = new ScService();

    // 合法的开始时间集合（与前端 timeOptions 一致）
    private static final Set<String> VALID_START_TIMES = new HashSet<>(Arrays.asList(
            "08:30", "09:25", "10:30", "11:25",
            "14:00", "14:55", "16:00", "16:55",
            "19:00", "19:55"
    ));

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        handleRequest(req, resp, "add");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        handleRequest(req, resp, "update");
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        handleRequest(req, resp, "delete");
    }

    private void handleRequest(HttpServletRequest req, HttpServletResponse resp, String action) throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json;charset=UTF-8");
        PrintWriter out = resp.getWriter();

        try {
            HttpSession session = req.getSession();
            Integer studentId = (Integer) session.getAttribute("studentId");
            if (studentId == null) {
                sendJson(out, false, "未登录");
                return;
            }

            // 读取 JSON 请求体
            StringBuilder sb = new StringBuilder();
            String line;
            try (BufferedReader reader = req.getReader()) {
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
            JSONObject json = JSON.parseObject(sb.toString());

            boolean success = false;
            String message = "";

            switch (action) {
                case "add": {
                    Sc sc = json.toJavaObject(Sc.class);
                    // 后端校验
                    String errorMsg = validateCourse(sc, studentId, false);
                    if (errorMsg != null) {
                        sendJson(out, false, errorMsg);
                        return;
                    }
                    sc.setStudentId(studentId);
                    success = scService.addCourse(sc);
                    message = success ? "课程添加成功" : "添加失败";
                    break;
                }
                case "update": {
                    Sc sc = json.toJavaObject(Sc.class);
                    if (sc.getId() == null) {
                        sendJson(out, false, "缺少课程ID");
                        return;
                    }
                    // 后端校验
                    String errorMsg = validateCourse(sc, studentId, true);
                    if (errorMsg != null) {
                        sendJson(out, false, errorMsg);
                        return;
                    }
                    success = scService.updateCourse(sc);
                    message = success ? "课程更新成功" : "更新失败";
                    break;
                }
                case "delete": {
                    Integer scId = json.getInteger("id");
                    if (scId == null) {
                        sendJson(out, false, "缺少课程ID");
                        return;
                    }
                    success = scService.deleteCourse(scId);
                    message = success ? "课程删除成功" : "删除失败";
                    break;
                }
                default:
                    sendJson(out, false, "不支持的操作");
                    return;
            }

            sendJson(out, success, message);

        } catch (Exception e) {
            e.printStackTrace();
            sendJson(out, false, "服务器错误: " + e.getMessage());
        } finally {
            out.flush();
        }
    }

    /**
     * 校验课程数据合法性
     * @param sc 课程对象
     * @param studentId 学生ID
     * @param isUpdate 是否为更新操作
     * @return 错误信息，null 表示合法
     */
    private String validateCourse(Sc sc, Integer studentId, boolean isUpdate) {
        // 1. 必填字段
        if (sc.getName() == null || sc.getName().trim().isEmpty()) {
            return "课程名称不能为空";
        }
        if (sc.getLocation() == null || sc.getLocation().trim().isEmpty()) {
            return "上课地点不能为空";
        }
        if (sc.getDayOfWeek() == null || sc.getDayOfWeek() < 1 || sc.getDayOfWeek() > 7) {
            return "星期必须为1-7";
        }
        if (sc.getStartTime() == null) {
            return "开始时间不能为空";
        }
        if (sc.getEndTime() == null) {
            return "结束时间不能为空";
        }

        // 2. 时间段合法性（必须在预定义列表中）
        if (!VALID_START_TIMES.contains(sc.getStartTime())) {
            return "开始时间无效，请选择标准课表时间段（如 08:30, 09:25 等）";
        }

        // 3. 冲突检测（查询同学生、同 dayOfWeek、同 startTime 的课程）
        List<Sc> existingList = scService.getCoursesByStudentIdAndTime(
                studentId, sc.getDayOfWeek(), sc.getStartTime()
        );

        for (Sc existing : existingList) {
            // 如果是更新操作，且冲突课程就是自己，则跳过
            if (isUpdate && Objects.equals(existing.getId(), sc.getId())) {
                continue;
            }
            // 发现冲突
            return "时间冲突：该时段（周" + sc.getDayOfWeek() + " " + sc.getStartTime() + "）已有课程《" + existing.getName() + "》";
        }

        return null; // 合法
    }

    private void sendJson(PrintWriter out, boolean success, String message) {
        JSONObject res = new JSONObject();
        res.put("success", success);
        res.put("message", message);
        out.print(res.toJSONString());
    }
}